﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWMAG.Scripting.AST.ObjectModel;
using IWMAG.Scripting.AST.TerminalExpressions;
using IWMAG.Scripting.Interpreter;
using IWMAG.Scripting.Types;
using IWMAG.Scripting.Compiler.UserInfo;

namespace IWMAG.Scripting.AST.Operators {
    internal class LateBindOperator : AssignmentOperator {
        public LateBindOperator(Compiler.Lexeme l, CodeExpression lval, CodeExpression val): base(l, lval, val) {
        }

        public override void Verify(Helpers.CompileTable sym, List<Compiler.IUserInfo> error) {
            sym.OpenScope();

            LHS.Verify(sym, error);
            CodeType t = sym.Dealias(LHS.TypeOf());

            sym.Lookahead[typeof(ValueExpression)] = () => t;
            sym.Lookahead[GetType()] = () => (LHS as VariableExpression).Name;
            RHS.Verify(sym, error);

            if (!t.Equals(sym.Dealias(RHS.TypeOf()))) {
                SendError(error,Rules.IncompatibleTypesInAssignment, RHS.TypeOf().ToString(),LHS.TypeOf().ToString());
            }

            if (LHS is MemberOperator) {
            } else if (LHS is IndexOperator) {
            } else if (LHS is VariableExpression) {
            } else {
                SendError(error,Rules.NonLValueInAssignmentAsAssignee);
            }

            sym.CloseScope();
        }

        public override IEnumerable<Continuation> ValueOf(Interpreter.ScriptEngine engine, Helpers.RuntimeTable sym, Interpreter.Reference<Interpreter.RunValue> val) {
            sym.OpenScope();
            sym.Passback[typeof(ValueExpression)] = (a) => {
                return sym.Variables[(LHS as VariableExpression).Name].LateBinding;
            };

            Reference<RunValue> me = RunValue.NoValue;
            me.ReferencedValue.MakeLate(engine, sym, RHS);
            sym.CloseScope();


            sym.Variables[(LHS as VariableExpression).Name] = me;

            yield break;
        }
    }
}
